#coding:utf-8

import os,sys,subprocess,json,types
from CollectSpider.service.task import  Task,init_engine,every_day,update_taskstatus_by_id
from CollectSpider.config.config import URL_LIST
from exceptions import Exception
from CollectSpider.kancloud import db
from time import sleep
from CollectSpider.globalvar.globalvar import task_list,subprocess_list,time_list
from CollectSpider.kancloud.MsgSend import MsgSend

#获取脚本文件的当前路径
def cur_file_dir():
    #获取脚本路径
    path = sys.path[0]
    #判断为脚本文件还是py2exe编译后的文件，如果是脚本文件，则返回的是脚本的目录，如果是py2exe编译后的文件，则返回的是编译后的文件路径
    if os.path.isdir(path):
        return path
    elif os.path.isfile(path):
        return os.path.dirname(path)
#获取任务 
def get_task():
    task=Task()
    return task.getAll()
#获取任务 
def get_task_by_id(taskid):
    task=Task()
    return task.get_task_by_id(taskid)
#检查数据库中的状态
def check_db_status():
    task=Task()
    temp_taskids=[]
    run_taskids=[]
    del_ids=[]
    insert_ids=[]
    del_list=[]
    insert_list=[]
    temp_tasklist=task.getAll()
    for temp_task in temp_tasklist:
        temp_taskids.append(temp_task["id"])

    for run_task in task_list:
        run_taskids.append(run_task["id"])
        
    for run_id in run_taskids:
        if run_id not in temp_taskids:
            del_ids.append(run_id)
    
    for temp_id in temp_taskids:
        if temp_id not in run_taskids:
            insert_ids.append(temp_id)
            
    for insert_id in insert_ids:
        temp_task=db.select("select * from spider_task where id=?",insert_id)
        insert_list.append(temp_task)
#     for delete_id in del_ids:
#         temp_task=db.select("select * from spider_task where id=?",delete_id)
#         del_list.append(temp_task)
    
    return {"insert":insert_list,"del":del_ids}
    
#更新循环体变量
def kill_subprc_by_task(task,runing_tasklist):
    #检查任务变化情况
    dictlist=check_db_status()
    del_ids=dictlist["del"]
    if del_ids is not None and set(runing_tasklist).issubset(set(del_ids)):
        #杀掉进程
        if subprocess_list is not None:           
            for run_id in runing_tasklist:
                subprc=get_subprocess_task(run_id)
                if subprc.returncode==None and subprc is not None:  
                    #杀掉子进程   
                    subprc.kill()
                    #修改状态
                    update_taskstatus_by_id(run_id)
    
   
def get_subprocess_task(task_id):
    sub_pro=None
    for subprc in subprocess_list:
        taskid=subprc.keys()[0]
        if taskid==task_id:
            sub_pro=subprc.get(taskid)
            break;
    return sub_pro

#根据调度的类型 来  运行爬虫
def run_way(task):
    if task is None and type(task)==types.DictType:
        raise ValueError("params error")
    else:
        #类型为2  定天运行
        if(int(task["schedule_type"])==2):
            #获取该类型可用的时间,并初始化全局的  可用时间列表,必须的 
            dispatch_spider(task)

        #类型为1  及时运行
        elif(int(task["schedule_type"])==1):
            #代表重复执行,的时间间隔，不标记 -1
            if int(task["time_interval"])>0:
                every_day(task["id"])
            
                if time_list is not None:
                #定天执行spider
                    dispatch_spider(task)
                else:
                    print "任务id:%s ,时间可能超时，没有合适运行时间点,不予执行" % task["id"]
            #代表执行单次，执行之后标记为 -1
            elif int(task["time_interval"])==0:
                dispatch_spider(task)
            else:
                print "任务id:%s 调度方式为1 单次运行， 并且任务 已经执行过，不予执行" % task["id"]
                
def init_tasklist():
    tasklists=get_task()
    for task in tasklists:
        task_list.append(task)
        
def init_tasklist_by_id(taskid):
    task=get_task_by_id(taskid)
    task_list.append(task) 
         
def check_task():
        #加入while循环，如果任务全部完成，就退出循环
        #初始化全局 的任务列表
        runing_tasklist=[] 
        init_tasklist_by_id(18)
        if task_list is not None:
            for task in task_list:
                
                dictlist=check_db_status()
                del_ids=dictlist["del"]
                current_taskid=task["id"]
                if del_ids is not None and current_taskid in del_ids:
                    print "数据库中设定不执行，应跳过"
                    continue
                else:
                    url=task["url_start"]
                    task_status=task["task_status"]
                    print "开始检查开始路径：",url
                    if url in URL_LIST.values():
                        #传参到调度脚本
                        if task_status==2:
                            print "合法路径,开始爬虫调度:",url
                            runing_tasklist.append(task["id"])
                            run_way(task) #根据任务类型 自动  使用相对应的调度方式
                        else:
                            print "该任务正在执行"
                        
                    else:
                        #发出警告，开始路径有误!
                        MsgSend.send_msg(**dict({"message":"任务id:"+str(task["id"])+" start_url 无效，不予执行","code":401,"extra":"启动时路径检查错误"}))
                        print "无效start_url",url
                
                    #检查任务变化情况
                    kill_subprc_by_task(task,runing_tasklist)
        else:
            print "没有可执行的任务!请知悉"
                        
#调度程序
def dispatch_spider(kwargs):
    try:
        #加载调度程序:
        dispatch=cur_file_dir()+os.sep+"dispatch_spider.py"
        #构造参数
        if kwargs is not None:
            params=json.dumps(dict(kwargs), ensure_ascii=False)
            child = subprocess.Popen(["python",dispatch,params])
            print "spider load success:", child.pid
            #维护子进程对象列表
            subprocess_list.append({kwargs["id"]:child})
            print "dispatch_spider exit, code:", child.returncode
        else:
            #发出警告,任务参数有误!
            print "参数有误"
            
    except Exception,e:
        
        print e
        
        
    
if __name__=='__main__':
    init_engine()
#     while True:
    check_task()
    sleep(3)
    

